#pragma strict

import System.Collections.Generic;

var max_floors:int;
var patients_per_floor:int;

var first_bed_offset:Vector3;
var distance_between_beds:float;
var floor_height:float;

var bed_prefab:Transform;

private var working_level_list:List.<LevelConfig>;
private var level_count:int;
private var current_level:int;
private var code_txt:String;

function Start () {
	current_level = 0;
	code_txt = "";
	
	if (CustomLevelManager.Instance().IsPlayingCustom()) {
		working_level_list = new List.<LevelConfig>(CustomLevelManager.Instance().GetCustomLevel());
		current_level = 0;
		level_count = working_level_list.Count;		
	}
	else {	
		working_level_list = new List.<LevelConfig>();
		AddLevel();			
	}
	
	var i:int;
	var j:int;
	for (i = 0; i < max_floors; i++) {
		for (j = 0; j < patients_per_floor; j++) {
			var bed_pos:Vector3 = first_bed_offset + Vector3(distance_between_beds * j, floor_height * i, 0);
			
			Instantiate(bed_prefab, bed_pos, Quaternion.identity);						
		}
	}
}

function CurrentDeathLimit() : int {
	return working_level_list[current_level].death_limit;
}

function CurrentTimeLimit() : int {
	return working_level_list[current_level].time_limit;
}

function SetCurrentDeathLimit(val:int) {
	working_level_list[current_level].death_limit = val;
}

function SetCurrentTimeLimit(val:float) {
	working_level_list[current_level].time_limit = val;
}

function Update () {

}

function ChangePatient(floor:int, patient:int) {
	var curr_patient:int = working_level_list[current_level].patients[((max_floors - floor - 1) * patients_per_floor) + patient];
	working_level_list[current_level].patients[((max_floors - floor - 1) * patients_per_floor) + patient] = (curr_patient + 1) % 3;	
}

function PatientToString(floor:int, patient:int) : String {
	if (working_level_list[current_level] != null) {		
		//return (working_level_list[current_level].patients[(floor * patients_per_floor) + patient]).ToString();
		var curr_patient:int = working_level_list[current_level].patients[((max_floors - floor - 1) * patients_per_floor) + patient];
		if (curr_patient == 0) return "EMPTY";
		else if (curr_patient == 1) return "+";
		else if (curr_patient == 2) return "-";
		else return "EMPTY";
	}
	else return "NULL";
}

function OnGUI() {
	var screen_height:int = Screen.height;
	var screen_width:int = Screen.width;
	var elevator_width:int = 90;
	var menu_height:int = 40;
	
	var i:int;
	var j:int;
	
	GUILayout.BeginArea(Rect(0,menu_height,screen_width - elevator_width, screen_height - menu_height), "", "box");	
		GUILayout.BeginVertical();					
			for (i = 0; i < max_floors; i++) {
				GUILayout.BeginHorizontal();
					for (j = 0; j < patients_per_floor; j++) {					
						if (GUILayout.Button(PatientToString(i,j), GUILayout.Width((screen_width - elevator_width) / patients_per_floor)
						,GUILayout.Height((screen_height - menu_height) / max_floors))) {
							ChangePatient(i,j);
						}
							
					}									
				GUILayout.EndHorizontal();
			}
		GUILayout.EndVertical();
	GUILayout.EndArea();
	
	var old_label_fontsize = GUI.skin.label.fontSize;
	var old_button_fontsize = GUI.skin.button.fontSize;
	
	GUI.skin.label.fontSize = 12;
	GUI.skin.button.fontSize = 12;
	
	GUILayout.BeginArea(Rect(screen_width - elevator_width,menu_height,elevator_width, screen_height - menu_height), "", "box");
		GUILayout.BeginVertical("box", GUILayout.Height(screen_height - menu_height));
			/* Level Count */
			GUILayout.Label("Level Count");
			GUILayout.BeginHorizontal();				
				
				if (level_count <= 1) GUI.enabled = false;
				if (GUILayout.Button("-")) {
					RemoveLevel();
				}
				GUI.enabled = true;						
				GUILayout.Label(level_count.ToString());
				if (GUILayout.Button("+")) {
					AddLevel();
				}		
			GUILayout.EndHorizontal();	
			
			/* Current Level */
			
			GUILayout.Label("Current Level");
			GUILayout.BeginHorizontal();				
				if (current_level <= 0) GUI.enabled = false;
				if (GUILayout.Button("-")) {
					current_level--;
				}
				GUI.enabled = true;	
				GUILayout.Label((current_level + 1).ToString());			
				if (current_level >= (level_count - 1)) GUI.enabled = false;
				if (GUILayout.Button("+")) {
					current_level++;
				}			
				GUI.enabled = true;	
			GUILayout.EndHorizontal();	
			
			/* Death Limit */
			
			GUILayout.Label("Death Limit");
			GUILayout.BeginHorizontal();				
				if (CurrentDeathLimit() <= 0) GUI.enabled = false;
				if (GUILayout.Button("-")) {
					SetCurrentDeathLimit(CurrentDeathLimit() - 1);
				}
				GUI.enabled = true;	
				GUILayout.Label((CurrentDeathLimit()).ToString());							
				if (GUILayout.Button("+")) {
					SetCurrentDeathLimit(CurrentDeathLimit() + 1);
				}			
				GUI.enabled = true;	
			GUILayout.EndHorizontal();	
			
			/* Time Limit */
			
			GUILayout.Label("Time Limit");
			GUILayout.BeginHorizontal();				
				if (CurrentTimeLimit() <= 0) GUI.enabled = false;
				if (GUILayout.Button("-")) {
					SetCurrentTimeLimit(CurrentTimeLimit() - 5);
				}
				GUI.enabled = true;	
				GUILayout.Label((CurrentTimeLimit()).ToString());							
				if (GUILayout.Button("+")) {
					SetCurrentTimeLimit(CurrentTimeLimit() + 5);
				}			
				GUI.enabled = true;	
			GUILayout.EndHorizontal();
			GUILayout.Label("");			
			if (GUILayout.Button("Export")) {
				code_txt = ExportToCode();
			}			
			code_txt = GUILayout.TextField(code_txt);
			if (GUILayout.Button("Import")) {
				ImportFromCode(code_txt);
			}
			GUILayout.Label("");
			if (GUILayout.Button("Play")) {
				CustomLevelManager.Instance().SetCustomLevel(GetWorkingLevelArray());				
				CustomLevelManager.Instance().SetPlayingCustom(true);
				Application.LoadLevel("GameScene");
			}
			GUILayout.Label("");			
			if (GUILayout.Button("Exit")) {
				CustomLevelManager.Instance().SetPlayingCustom(false);
				CustomLevelManager.Instance().SetCustomLevel(null);
				Application.LoadLevel("MenuScene");
			}
		GUILayout.EndVertical();
	GUILayout.EndArea();
	GUI.skin.label.fontSize = old_label_fontsize;
	GUI.skin.button.fontSize = old_button_fontsize;
}

function IsCodeValid(code:String) {
	Debug.Log("Code Length: " + code.Length);
	if (code.Length >= 0 && code.Length % 14 == 0) return true;
	else return false;
}

function ImportFromCode(code:String) {
	if (IsCodeValid(code)) {		
		var l:int = 0;
		var char_pointer:int = 0;
		var code_len:int = code.Length;
		
		var code_array:char[] = code.ToCharArray();
		
		working_level_list = new List.<LevelConfig>();
		
		while (char_pointer < code_len) {		
			AddLevel();	
			var death_limit:byte = 0;
			var time_limit:short = 0;
			
			death_limit |= HexConverter.HexToInt(code_array[char_pointer]) << 4;
			char_pointer++;
			death_limit |= HexConverter.HexToInt(code_array[char_pointer]);
			char_pointer++;
			
			time_limit |= HexConverter.HexToInt(code_array[char_pointer]) << 12;
			char_pointer++;
			time_limit |= HexConverter.HexToInt(code_array[char_pointer]) << 8;
			char_pointer++;
			time_limit |= HexConverter.HexToInt(code_array[char_pointer]) << 4;
			char_pointer++;
			time_limit |= HexConverter.HexToInt(code_array[char_pointer]) ;
			char_pointer++;
			
			var i:int = 0;
			var j:int = 0;
			
			working_level_list[l].patients = new int[max_floors * patients_per_floor];
			
			for (i = 0; i < max_floors; i++) {			
				var floor_byte:byte = 0;
				floor_byte |= HexConverter.HexToInt(code_array[char_pointer]) << 4;
				char_pointer++;
				floor_byte |= HexConverter.HexToInt(code_array[char_pointer]);
				char_pointer++;
				
				for (j = 0; j < patients_per_floor; j++) {															
					var patient_val:byte = floor_byte;
					patient_val &= (0x03 << 6 - (j * 2));
					patient_val >>= (6 - (j * 2));
					Debug.Log("i: " + i);
					Debug.Log("j: " + j);
					Debug.Log("Patient val: " + patient_val);								
					working_level_list[l].patients[(i * patients_per_floor) + j] = patient_val;
				}						
			}
			working_level_list[l].death_limit = death_limit;
			working_level_list[l].time_limit = time_limit * 5;
			l++;
		}
		current_level = 0;
		level_count = l;
	}
}

function ExportToCode() : String {	
	var result:String = "";
	
	var i:int = 0;
	var j:int = 0;
	var l:int = 0;	
	
	for (var lvl:LevelConfig in working_level_list) {					
		var floor_death_byte:byte = lvl.death_limit;		
		var floor_death_char1:char = HexConverter.GetHex(floor_death_byte >> 4);
		var floor_death_char2:char = HexConverter.GetHex(floor_death_byte & 0x0F);
		
		var floor_time:short = lvl.time_limit / 5;		
		var floor_time_char1:char = HexConverter.GetHex((floor_time & 0xF000 ) >> 12);
		var floor_time_char2:char = HexConverter.GetHex((floor_time & 0x0F00 ) >> 8);
		var floor_time_char3:char = HexConverter.GetHex((floor_time & 0x00F0 ) >> 4);
		var floor_time_char4:char = HexConverter.GetHex((floor_time & 0x000F ));
		
		result += floor_death_char1; 
		result += floor_death_char2; 
		
		result += floor_time_char1; 
		result += floor_time_char2; 
		result += floor_time_char3; 
		result += floor_time_char4; 
		
		for (i = 0; i < max_floors; i++) {			
			var floor_byte:byte = 0;
			for (j = 0; j < patients_per_floor; j++) {															
				var patient_val:int;
				patient_val = lvl.patients[(i * patients_per_floor) + j];
				Debug.Log("i: " + i);
				Debug.Log("j: " + j);
				Debug.Log("Patient val: " + patient_val);				
				floor_byte |= ((patient_val << 6) >> (j * 2));				
			}			
			result += HexConverter.GetHex((floor_byte & 0xF0 ) >> 4);
			result += HexConverter.GetHex((floor_byte & 0x0F ));
		}
	}
	Debug.Log("Result: " + result);
	return result;
		
}


function AddLevel() {
	if (working_level_list != null) {
		var lvl_config = new LevelConfig();
		lvl_config.patients = new int[max_floors * patients_per_floor];
		lvl_config.time_limit = 30;
		working_level_list.Add(lvl_config);
		level_count++;
	}
}

function RemoveLevel() {
	if (working_level_list != null) {		
		working_level_list.RemoveAt(level_count - 1);
		level_count--;
		if (current_level == level_count) current_level--;
	}
}

function GetWorkingLevelArray() : LevelConfig[] {
	return working_level_list.ToArray();
}